/*接在寄存器前面的第一个选择器，决定需要写入的寄存器是来自rt还是rd，RegDes是控制器发来的信号*/
module MuxReg (
    input [4:0] rt,
    input [4:0] rd,
    input [1:0] RegDes,
    output reg [4:0] des_reg
);
    parameter   RT_RegDst = 2'b01, RD_RegDst = 2'b00,RA_RegDst=2'b10;                           // RegDst                   // RegDst
   
    always @(*) begin
        if(RegDes==RT_RegDst)
            des_reg = rt;
        else if(RegDes==RD_RegDst)
            des_reg = rd;
        else if(RegDes==RA_RegDst)
            des_reg = 5'b11111;
    end
endmodule //mux_reg

/*接在alu前面的选择器 ，决定ALU第二个输入数据是立即数还是rt*/
module MuxHazardRs (
    input [1:0]   hazard,
    input [31:0]  data_rs,
    input [31:0]  data_ex_mem,
    input [31:0]  data_mem_wb,
    output reg [31:0] data  
);
    parameter NO_HAZARD = 2'b00,HAZARD_EX_MEM = 2'b01,HAZARD_MEM_WB=2'b10; 
    always @(*) begin
        if(hazard==HAZARD_EX_MEM)
            data = data_ex_mem;
        else if(hazard==HAZARD_MEM_WB)
            data = data_mem_wb;
        else
            data = data_rs;
    end

endmodule //mux
module MuxRt (
    input [31:0] data_rt,
    input [31:0] immediate,
    input AluSrc,
    output reg [31:0] data
);
parameter   RD2 = 1'b1, IMMEDIATE_NUMBER = 1'b0;            // AluSrc
    always @(*)
    begin
        if(AluSrc==RD2)
        data = data_rt;
    else
        data = immediate;
    end
endmodule //mux
module MuxHazardRt (
    input [31:0] data_rt,
    
    input [1:0]   hazard,
    input [31:0]  data_ex_mem,
    input [31:0]  data_mem_wb,
    output reg [31:0] data
);
    parameter NO_HAZARD = 2'b00,HAZARD_EX_MEM = 2'b01,HAZARD_MEM_WB=2'b10; 
    always @(*) begin
        begin
            if(hazard==HAZARD_EX_MEM)
                    data = data_ex_mem;
                else if(hazard==HAZARD_MEM_WB)
                    data = data_mem_wb;
                else
                    data = data_rt;
        end        
    end
endmodule //mux_alu
  //MuxAlu mux_alu(rd2, {{16{instr[15]}}, instr[15:0]}, AluSrc, b);
/*接在reg前面的选择器，用来选择写入的数据是alu计算结果还是从内存读入*/
module MuxRegData (
    dout, //内存读入的数据
    result, //ALU计算结果
    pc,
    MemtoReg, //可以写的信号
    writedata
);
    input [31:0]     dout;
    input [31:0]     result;
    input [31:0]     pc;
    input [1:0]      MemtoReg;
   
    output reg[31:0] writedata; 
    parameter   DMOUT_MemtoReg = 2'b01, ALURESULT_MemtoReg = 2'b00,PC_MemtoReg=2'b10;                 // MemtoReg
    always @(*) begin
        if(MemtoReg==DMOUT_MemtoReg)
            writedata = dout;
        else if(MemtoReg==ALURESULT_MemtoReg)
            writedata = result;
        else if(MemtoReg==PC_MemtoReg)
            writedata = pc;
    end
endmodule //mux


//接在PC前面的选择器
module MuxPc (
    PcSrc,
    pc_adder_in,
    ex_mem_reg_in,
    pc_out
);
    input PcSrc;
    input [31:0] pc_adder_in;
    input [31:0] ex_mem_reg_in;
    output reg [31:0] pc_out; 
    always @(*) begin
        if(PcSrc)
            pc_out = ex_mem_reg_in;
        else
            pc_out = pc_adder_in;
            
    end
endmodule //mux


module MuxBranchA (
    input [1:0]   hazard,
    input [31:0]  data_rs,
    input [31:0]  data_ex_mem,
    input [31:0]  data_mem_wb,
    output reg [31:0] data  
);
    parameter NO_HAZARD = 2'b00,HAZARD_EX_MEM = 2'b01,HAZARD_MEM_WB=2'b10; 
    always @(*) begin
        if(hazard==HAZARD_EX_MEM)
            data = data_ex_mem;
        else if(hazard==HAZARD_MEM_WB)
            data = data_mem_wb;
        else
            data = data_rs;
    end

endmodule //mux


module MuxBranchB (
    input [1:0]   hazard,
    input [31:0]  data_rt,
    input [31:0]  data_ex_mem,
    input [31:0]  data_mem_wb,
    output reg [31:0] data  
);
    parameter NO_HAZARD = 2'b00,HAZARD_EX_MEM = 2'b01,HAZARD_MEM_WB=2'b10; 
    always @(*) begin
        if(hazard==HAZARD_EX_MEM)
            data = data_ex_mem;
        else if(hazard==HAZARD_MEM_WB)
            data = data_mem_wb;
        else
            data = data_rt;
    end

endmodule //mux